#include "CalcLogic.h"
#include <math.h>
#include <QDebug>
#include <QVariant>

const QString digits("0123456789");
const QString KArithematicOperators("+,-,*,/,%");
const QString KHexAlphabets("ABCDEF");

CalcLogic::CalcLogic(QObject *parent) :
        QObject(parent),
        mCalcMode(BasicMode),
        mCurrentUnitsType(Radians),
        mWordType(QWord),
        mRadixType(Dec),
        mCurrentOperatorType(CalcLogic::None),
        mUserInput(""),
        mUserInputOperand(),
        mBraceCounter(0),
        ch(""),
        mCurrentResult(0),
        mDecimalValue(0)
{
    calculator = new Calc_var;
    mvalueinMemory = 0;
}

void CalcLogic::setMode(CalcMode mode)
{
    mBraceCounter=0;
    emit updateBraceCounter("");
    mUserInput.clear();
    mUserInputOperand.clear();
    this->mCalcMode = mode;
}

CalcMode CalcLogic::mode()
{
    return mCalcMode;
}

UnitsType CalcLogic::unitsType()
{
    return mCurrentUnitsType;
}

void CalcLogic::buttonPressed(QAbstractButton* button)
{
    CalcLogic::OperatorType opType= operatorType(button->text());
    // handling digits
    if( isDigit(button->text()) ||
        opType == CalcLogic::pivalue || // pi and 2pi are replaced with values.
        opType == CalcLogic::twopivalue ||
        isHexAlphabet(button->text())) {
        QString operand = button->text();
        // if prev operator is equalto then clear operand so that the new digit entered in not appended.
        if(Equal == mCurrentOperatorType) {
            mUserInputOperand.clear();
            mCurrentOperatorType = None;
        }
        else if(CalcLogic::power == mCurrentOperatorType ||
                CalcLogic::yrootofx == mCurrentOperatorType ||
                CalcLogic::Mod == mCurrentOperatorType) {
            mUserInput.append(button->text());
            formatAndUpdateConsole(mUserInput,evaluateExpression(mUserInput));
            return;
        }
        // for pi and two pi replace it with the corresponding values.
        if( opType == CalcLogic::pivalue ) {
            operand = operand.setNum(M_PI);
        }
        else if(opType == CalcLogic::twopivalue ) {
            operand = operand.setNum(2*M_PI);
        }
        mUserInputOperand.append(operand);
        formatAndUpdateConsole(mUserInput,mUserInputOperand.toDouble());
        if( ProgramMode == mode() ){

            handleInputInProgramMode(mUserInputOperand);
            emit resultAvailable(mUserInputOperand);
            emit byteResultAvailable(convertDecToBin(mUserInputOperand.toInt()));
        }
    }
    //        if( ProgramMode == mode() ){
    //                    if(isHexAlphabet(button->text())) {
    //                        mUserInput.append(button->text());
    //                        emit resultAvailable(mUserInput);
    //                    }
    //                    handleInputInProgramMode(mUserInputOperand);
    //                }
    //                else
    //                    formatAndUpdateConsole(mUserInput,mUserInputOperand.toDouble());
    //            }
    // handling operator
    else {
        switch(opType)
        {
        case CalcLogic::Addtion:
        case CalcLogic::Substraction:
        case CalcLogic::Multiplication:
        case CalcLogic::Division:
        case CalcLogic::Percent:{
                ch = button->text();
                mUserInput.append(mUserInputOperand + button->text());
                mCurrentResult = evaluateExpression(mUserInput);
                formatAndUpdateConsole(mUserInput,mCurrentResult);
                mUserInputOperand.clear();
                break;
            }
        case CalcLogic::power: {
                ch = button->text();
                mUserInput += mUserInputOperand + "p";
                formatAndUpdateConsole(mUserInput,mCurrentResult);
                mUserInputOperand.clear();
                break;
            }
        case CalcLogic::yrootofx:{
                ch = button->text();
                mUserInput += mUserInputOperand + "yroot";
                formatAndUpdateConsole(mUserInput,mCurrentResult);
                mUserInputOperand.clear();
                break;
            }
        case CalcLogic::Mod:{
                ch = button->text();
                mUserInput += mUserInputOperand + "mod";
                formatAndUpdateConsole(mUserInput,mCurrentResult);
                mUserInputOperand.clear();
                break;
            }
        case CalcLogic::PlusMinus:{
                double rightHandSide = mUserInputOperand.toDouble();
                mUserInputOperand = QString().setNum(-1 * rightHandSide);
                emit resultAvailable("\n"+mUserInputOperand);
                break;
            }
        case CalcLogic::mantissa:{
                double rightHandSide = mUserInputOperand.toDouble();
                bool isNegative = false;
                if(signbit(rightHandSide)){
                    isNegative = true;
                    rightHandSide = fabs(rightHandSide);
                }
                int count = 0;
                if(rightHandSide>= 10)
                {
                    while(rightHandSide >=10)
                    {
                        rightHandSide = rightHandSide*0.1; count++;
                    }
                }
                else
                {
                    while(rightHandSide <=1)
                    {
                        rightHandSide = rightHandSide*10; count--;
                    }
                }
                if(isNegative)
                {
                    rightHandSide = rightHandSide*-1.0;
                }
                QString str1 = QString().setNum(rightHandSide);
                QString str2 = "e";
                QString str3 = QString().setNum(count);
                mUserInput=str1+str2+str3;
                emit resultAvailable(mUserInput);
                break;
            }
        case CalcLogic::exponentialvalue:{
                QString str = "e";
                mUserInputOperand+=str;
                emit resultAvailable(mUserInputOperand);
                break;
            }
        case CalcLogic::Equal:{
                handleEqualTo();
                break;
            }
        case CalcLogic::Dot:{
                if (!mUserInputOperand.contains("."))
                    mUserInputOperand.append(button->text());
                emit resultAvailable(mUserInput+"\n"+mUserInputOperand);
                break;
            }
        case CalcLogic::ClearOperand:{
                mUserInputOperand.clear();
                formatAndUpdateConsole(mUserInput,0);
                break;
            }
        case CalcLogic::ClearEverything:{
                clearEverything();
                break;
            }
        case CalcLogic::Backspace:{
                mUserInputOperand.chop(1);
                formatAndUpdateConsole(mUserInput,mUserInputOperand.toDouble());
                break;
            }
        case CalcLogic::MemoryPlus:{
                mvalueinMemory +=mUserInputOperand.toDouble();
                formatAndUpdateConsole("",mvalueinMemory);
                break;
            }
        case CalcLogic::MemoryMinus:{
                mvalueinMemory -=mUserInput.toDouble();
                emit resultAvailable(mUserInput);
                break;
            }
        case CalcLogic::MemoryStore:{
                mvalueinMemory=mUserInputOperand.toDouble();
                emit resultAvailable(mUserInput);
                break;
            }
        case CalcLogic::MemoryRead:{
                mUserInput = QString().setNum(mvalueinMemory);
                emit resultAvailable(mUserInput);
                break;
            }
        case CalcLogic::MemoryClear:{
                mvalueinMemory=0;
                break;
            }
        case CalcLogic::BitwiseNot:{
                int rightHandSide = mUserInputOperand.toInt();
                mUserInputOperand = QString().setNum(~rightHandSide);
                emit resultAvailable("\n"+mUserInputOperand);
                break;
            }
        case CalcLogic::BitwiseAnd:{
                ch = button->text();
                mUserInput += QString().setNum(mDecimalValue) + "&";
                mUserInputOperand.clear();
                break;
            }
        case CalcLogic::BitwiseOr:{
                ch = button->text();
                mUserInput += QString().setNum(mDecimalValue) + "|";
                mUserInputOperand.clear();
                break;
            }
        case CalcLogic::BitwiseXor:{
                ch = button->text();
                mUserInput += QString().setNum(mDecimalValue) + "^";
                mUserInputOperand.clear();
                break;
            }
        case CalcLogic::LShift:{
                ch = button->text();
                mUserInput += QString().setNum(mDecimalValue) + "<";
                mUserInputOperand.clear();
                break;
            }
        case CalcLogic::Rshift:{
                ch = button->text();
                mUserInput += QString().setNum(mDecimalValue) + ">";
                mUserInputOperand.clear();
                break;
            }
        case CalcLogic::RotateLeft:{
                ch = button->text();
                mUserInput += QString().setNum(mDecimalValue) + "l";
                mUserInputOperand.clear();
                break;
            }
        case CalcLogic::RotateRight:{
                ch = button->text();
                mUserInput += QString().setNum(mDecimalValue) + "r";
                mUserInputOperand.clear();
                break;
            }
        case CalcLogic::sinvalue:
        case CalcLogic::cosvalue:
        case CalcLogic::tanvalue:
        case CalcLogic::sinhvalue:
        case CalcLogic::coshvalue:
        case CalcLogic::tanhvalue:
        case CalcLogic::asinvalue:
        case CalcLogic::acosvalue:
        case CalcLogic::atanvalue:
        case CalcLogic::asinhvalue:
        case CalcLogic::acoshvalue:
        case CalcLogic::atanhvalue:
        case CalcLogic::Sqroot:
        case CalcLogic::naturalLog:
        case CalcLogic::logvalue:
        case CalcLogic::cuberoot:
        case CalcLogic::Reciprocal:
        case CalcLogic::square:
        case CalcLogic::cube:
        case CalcLogic::factorial:
        case CalcLogic::Tenpowerx:
        case CalcLogic::epowerx:
        case CalcLogic::dmsvalue:
        case CalcLogic::todegress:
        case CalcLogic::Intvalue:
        case CalcLogic::Fracvalue:
            {
                if(mUserInputOperand.isEmpty()) {
                    return;
                }
                // get the proper function name depending on optype and current units type
                // append this name to userinput operand so that is becomes like sinr(90)
                mUserInput += functionNameForOperator(opType,this->unitsType()) +
                              "(" + mUserInputOperand + ")";
                mCurrentResult = evaluateExpression(mUserInput);
                formatAndUpdateConsole(mUserInput,mCurrentResult);
                mUserInputOperand.clear();
                break;
            }
        //Stastics mode
        case CalcLogic::AddToDataset:{
            if(StatisticsMode == mode()) {
            QString data = (mUserInputOperand.isEmpty())?("0"):(mUserInputOperand);
            mStatisticsDataset.append(data.toInt());
            emit addDatasetItem(data);
            emit resultAvailable(data);
            mUserInputOperand.clear();
            qDebug()<<"datset:"<<mStatisticsDataset;
            // All statistics operations should be done on mStatisticsDataset
            // Once any operation like sigma, mean are performed make sure to rest mStatisticsDataset
            // and emit clearDataset.
           }
        break;
        }

        default:{
                mCurrentOperatorType = opType;
                break;
            }
        }
        mCurrentOperatorType = opType;
    }

}

void CalcLogic::handleEqualTo()
{
    if(ProgramMode == mode()){
        if(mUserInput.contains("&")) {
            mUserInput += QString().setNum(mDecimalValue);
        }
        if(mUserInput.contains("|")) {
            mUserInput += QString().setNum(mDecimalValue);
        }
        if(mUserInput.contains("<")) {
            mUserInput += QString().setNum(mDecimalValue);
        }
        if(mUserInput.contains(">")) {
            mUserInput += QString().setNum(mDecimalValue);
        }
        if(mUserInput.contains("^")) {
            mUserInput += QString().setNum(mDecimalValue);
        }
        if(mUserInput.contains("l")) {
            mUserInput += QString().setNum(mDecimalValue);
        }
        if(mUserInput.contains("r")) {
            mUserInput += QString().setNum(mDecimalValue);
        }
    }
    else
    mUserInput += mUserInputOperand;
    mCurrentResult = evaluateExpression(mUserInput);
    mUserInput.clear();
    mUserInputOperand.setNum(mCurrentResult);
    formatAndUpdateConsole("",mCurrentResult);

    if(ProgramMode == mode()) {
        handleInputInProgramMode(QString().setNum(mCurrentResult));
        emit resultAvailable(convertDecToTargetRadix(mCurrentResult,mRadixType));
    }
}

QString CalcLogic::convertDecToTargetRadix(int decimalValue,RadixType radix) {
    QString convertedResult;
    switch(radix) {
    case Dec: {
        convertedResult = convertDecToDec(decimalValue);
        break;
    }
    case Bin: {
        convertedResult = convertDecToBin(decimalValue);
        break;
    }
    case Oct:{
        convertedResult = convertDecToOct(decimalValue);
        break;
    }
    case Hex:{
        convertedResult = convertDecToHex(decimalValue);
        break;
    }
    }
    return convertedResult;
}

void CalcLogic::handleDecClicked() {
    mRadixType=Dec;
    emit resultAvailable(convertDecToDec(mDecimalValue));
    mUserInputOperand.clear();
    // mRadixType=Dec;
    // formatAndUpdateConsole("",mDecimalValue);
}

void CalcLogic::handleBinClicked() {
    mRadixType=Bin;
    emit resultAvailable(convertDecToBin(mDecimalValue));
    mUserInputOperand.clear();
}

void CalcLogic::handleOctClicked() {
    mRadixType=Oct;
    emit resultAvailable(convertDecToOct(mDecimalValue));
    mUserInputOperand.clear();
}

void CalcLogic::handleHexClicked() {
    mRadixType=Hex;
    emit resultAvailable(convertDecToHex(mDecimalValue));
    mUserInputOperand.clear();
}

QString CalcLogic::convertDecToDec(int decimalValue) {
    return QString().setNum(decimalValue);
}

QString CalcLogic::convertDecToBin(int decimalValue) {
    int bin[100],i,j;
    for(i=0;decimalValue!=0;i++)
    {
        bin[i]=decimalValue%2;
        decimalValue=decimalValue/2;
    }
    QString binaryvalue;
    for(j=i-1;j>=0;j--)
    {
        QVariant v;
        v.setValue(bin[j]);
        QString s = v.toString();
        binaryvalue =binaryvalue + s;
    }
    return binaryvalue;
}

QString CalcLogic::convertDecToOct(int decimalValue) {
    int bin[100],i,j;
    for(i=0;decimalValue!=0;i++)
    {
        bin[i]=decimalValue%8;
        decimalValue=decimalValue/8;
    }
    QString octalvalue;
    for(j=i-1;j>=0;j--)
    {
        QVariant v;
        v.setValue(bin[j]);
        QString s = v.toString();
        octalvalue = octalvalue + s;
    }
    return octalvalue;
}

QString CalcLogic::convertDecToHex(int decimalValue)
{
    int bin[100],i,j;
    for(i=0;decimalValue!=0;i++)
    {
        bin[i]=decimalValue%16;
        decimalValue=decimalValue/16;
    }
    QString hexvalue;
    for(j=i-1;j>=0;j--)
    {
        QVariant v;
        v.setValue(bin[j]);
        QString s = v.toString();
        if(bin[j]==10)
            hexvalue = hexvalue + "A";
        else if(bin[j]==11)
            hexvalue = hexvalue + "B";
        else if(bin[j]==12)
            hexvalue = hexvalue + "C";
        else if(bin[j]==13)
            hexvalue = hexvalue + "D";
        else if(bin[j]==14)
            hexvalue = hexvalue + "E";
        else if(bin[j]==15)
            hexvalue = hexvalue + "F";
        else
            hexvalue = hexvalue + s;
    }
    return hexvalue;
}

void CalcLogic::handleQWordClicked() {
    mWordType = QWord;
    formatAndUpdateByteConsole(mUserInputOperand.toDouble(),QWord);
}

void CalcLogic::handleDWordClicked() {
    mWordType = DWord;
    formatAndUpdateByteConsole(mUserInputOperand.toDouble(),DWord);
}

void CalcLogic::handleWordClicked() {
    mWordType = Word;
    formatAndUpdateByteConsole(mUserInputOperand.toDouble(),Word);
}

void CalcLogic::handleByteClicked() {
    mWordType = Byte;
    formatAndUpdateByteConsole(mUserInputOperand.toDouble(),Byte);
}

void CalcLogic::handleInputInProgramMode(QString inputString) {
    QString inputhex = inputString;
    int input = inputString.toInt();
    // here we convert the input depending on the radixtype to decimal.
    switch(mRadixType) {
    case Bin: {
            int bnum,dec=0,base=1,rem ;
            bnum = input;
            while( input > 0)
            {
                rem = input % 10;
                dec = dec + rem * base;
                input = input / 10 ;
                base = base * 2;
            }
            mDecimalValue = dec;
            break;
        }
    case Oct: {
            int  bnum,dec = 0,base = 1,rem ;
            bnum = input;
            while( input > 0)
            {
                rem = input % 10;
                dec = dec + rem * base;
                input = input / 10 ;
                base = base * 8;
            }
            mDecimalValue =dec;
            break;
        }
    case Hex: {
            int number=0;
           // QVariant v;
           // v.setValue(input);
            QString str = inputhex;
            int ch,j=0;
            int i =str.count();
            while(i!=0)
            {
                QVariant v1;
                v1.setValue(str.at(j));
                ch = v1.toInt();
                if(('0' <= ch && ch <= '9'))
                {
                    number = number * 16;
                    number = number + (ch - '0');
                }
                if(('A' <= ch && ch && ch <= 'Z'))
                {
                    number = number * 16;
                    number = number + (ch - '7');
                }
                i--;
                j++;
            }
            mDecimalValue =number;
            break;
        }
    case Dec:
    default: {
            mDecimalValue = input;
        }
    }
}

bool CalcLogic::isDigit(QString text)
{
    return digits.contains(text,Qt::CaseInsensitive);
}

bool CalcLogic::isHexAlphabet(QString text)
{
    return KHexAlphabets.contains(text);
}

CalcLogic::OperatorType CalcLogic::operatorType(QString text)
{
    if(text.contains("+-"))
        return CalcLogic::PlusMinus;

    else if(!(text.compare(text,"+",Qt::CaseInsensitive)))
        return CalcLogic::Addtion;

    else if(text.contains("1/X"))
        return CalcLogic::Reciprocal;

    else if(!(text.compare(text,"-",Qt::CaseSensitive)))
        return CalcLogic::Substraction;

    else if(text.contains("*"))
        return CalcLogic::Multiplication;

    else if(text.contains("/"))
        return CalcLogic::Division;

    else if(text.contains("%"))
        return CalcLogic::Percent;

    else if(text.contains("sqrt"))
        return CalcLogic::Sqroot;

    else if(!(text.compare(text,"CE",Qt::CaseInsensitive)))
        return CalcLogic::ClearEverything;

    else if(!(text.compare(text,"Clear",Qt::CaseInsensitive)))
        return CalcLogic::ClearOperand;

    else if(text.contains("="))
        return CalcLogic::Equal;

    else if(text.contains("."))
        return CalcLogic::Dot;

    else if(text.contains("BackSpace"))
        return CalcLogic::Backspace;

    else if(!(text.compare(text,"M+",Qt::CaseInsensitive)))
        return CalcLogic::MemoryPlus;

    else if(!(text.compare(text,"MS",Qt::CaseInsensitive)))
        return CalcLogic::MemoryStore;

    else if(!(text.compare(text,"MR",Qt::CaseInsensitive)))
        return CalcLogic::MemoryRead;

    else if(!(text.compare(text,"MC",Qt::CaseSensitive)))
        return CalcLogic::MemoryClear;

    else if(!(text.compare(text,"M-",Qt::CaseSensitive)))
        return CalcLogic::MemoryMinus;

    else if(!(text.compare(text,"sin",Qt::CaseSensitive)))
        return CalcLogic::sinvalue;

    else if(!(text.compare(text,"cos",Qt::CaseSensitive)))
        return CalcLogic::cosvalue;

    else if(!(text.compare(text,"tan",Qt::CaseSensitive)))
        return CalcLogic::tanvalue;

    else if(!(text.compare(text,"sinh",Qt::CaseSensitive)))
        return CalcLogic::sinhvalue;

    else if(!(text.compare(text,"cosh",Qt::CaseSensitive)))
        return CalcLogic::coshvalue;

    else if(!(text.compare(text,"tanh",Qt::CaseSensitive)))
        return CalcLogic::tanhvalue;

    else if(!(text.compare(text,"x^y",Qt::CaseSensitive)))
        return CalcLogic::power;

    else if(!(text.compare(text,"x^2",Qt::CaseSensitive)))
        return CalcLogic::square;

    else if(!(text.compare(text,"x^3",Qt::CaseSensitive)))
        return CalcLogic::cube;

    else if(!(text.compare(text,"log",Qt::CaseSensitive)))
        return CalcLogic::logvalue;

    else if(!(text.compare(text,"n!",Qt::CaseSensitive)))
        return CalcLogic::factorial;

    else if(!(text.compare(text,"cuberoot",Qt::CaseSensitive)))
        return CalcLogic::cuberoot;

    else if(!(text.compare(text,"10^x",Qt::CaseSensitive)))
        return CalcLogic::Tenpowerx;

    else if(!(text.compare(text,"yrootx",Qt::CaseSensitive)))
        return CalcLogic::yrootofx;

    else if(!(text.compare(text,"Pie",Qt::CaseSensitive)))
        return CalcLogic::pivalue;

    else if(!(text.compare(text,"F-E",Qt::CaseSensitive)))
        return CalcLogic::mantissa;

    else if(!(text.compare(text,"Mod",Qt::CaseSensitive)))
        return CalcLogic::Mod;

    else if(!(text.compare(text,"dms",Qt::CaseSensitive)))
        return CalcLogic::dmsvalue;

    else if(!(text.compare(text,"ln",Qt::CaseSensitive)))
        return CalcLogic::naturalLog;

    else if(!(text.compare(text,"Exp",Qt::CaseSensitive)))
        return CalcLogic::exponentialvalue;

    else if(!(text.compare(text,"asin",Qt::CaseSensitive)))
        return CalcLogic::asinvalue;

    else if(!(text.compare(text,"acos",Qt::CaseSensitive)))
        return CalcLogic::acosvalue;

    else if(!(text.compare(text,"atan",Qt::CaseSensitive)))
        return CalcLogic::atanvalue;

    else if(!(text.compare(text,"asinh",Qt::CaseSensitive)))
        return CalcLogic::asinhvalue;

    else if(!(text.compare(text,"acosh",Qt::CaseSensitive)))
        return CalcLogic::acoshvalue;

    else if(!(text.compare(text,"atanh",Qt::CaseSensitive)))
        return CalcLogic::atanhvalue;

    else if(!(text.compare(text,"epowx",Qt::CaseSensitive)))
        return CalcLogic::epowerx;

    else if(!(text.compare(text,"deg",Qt::CaseSensitive)))
        return CalcLogic::todegress;

    else if(!(text.compare(text,"2Pie",Qt::CaseSensitive)))
        return CalcLogic::twopivalue;

    else if(!(text.compare(text,"Int",Qt::CaseSensitive)))
        return CalcLogic::Intvalue;

    else if(!(text.compare(text,"Frac",Qt::CaseSensitive)))
        return CalcLogic::Fracvalue;
 //program mode
    else if(!(text.compare(text,"Not",Qt::CaseSensitive)))
        return CalcLogic::BitwiseNot;

    else if(!(text.compare(text,"And",Qt::CaseSensitive)))
        return CalcLogic::BitwiseAnd;

    else if(!(text.compare(text,"Lsh",Qt::CaseSensitive)))
        return CalcLogic::LShift;

    else if(!(text.compare(text,"Rsh",Qt::CaseSensitive)))
        return CalcLogic::Rshift;

    else if(!(text.compare(text,"Or",Qt::CaseSensitive)))
        return CalcLogic::BitwiseOr;

    else if(!(text.compare(text,"Xor",Qt::CaseSensitive)))
        return CalcLogic::BitwiseXor;

    else if(!(text.compare(text,"RoL",Qt::CaseSensitive)))
        return CalcLogic::RotateLeft;

    else if(!(text.compare(text,"RoR",Qt::CaseSensitive)))
        return CalcLogic::RotateRight;
//statstics mode
    else if(!(text.compare(text,"Add",Qt::CaseSensitive)))
        return CalcLogic::AddToDataset;

    return CalcLogic::None;
}

void CalcLogic::degreesSelected()
{
    mCurrentUnitsType = Degrees;
}

void CalcLogic::radiansSelected()
{
    mCurrentUnitsType = Radians;
}

void CalcLogic::gradsSelected()
{
    mCurrentUnitsType = Grads;
}

void CalcLogic::openbraceSelected()
{

    if(mBraceCounter > 0)
    {
        mBraceCounter++;
    }
    else
    {
        mBraceCounter = 1;
    }
    emit updateBraceCounter("("+QString().setNum(mBraceCounter));
    mUserInput.append("(");
    mCurrentResult = evaluateExpression(mUserInput);
    formatAndUpdateConsole(mUserInput,mCurrentResult);
}

void CalcLogic::closebraceSelected()
{
    if(mBraceCounter) {
        mBraceCounter--;
        mUserInput += mUserInputOperand + ")";
    }
    if(mBraceCounter > 0)
    {
        emit updateBraceCounter("("+QString().setNum(mBraceCounter));
    }
    else
    {
        emit updateBraceCounter("");
    }
    mUserInputOperand.clear();
    mCurrentResult = evaluateExpression(mUserInput);
    formatAndUpdateConsole(mUserInput,mCurrentResult);
}

double CalcLogic::evaluateExpression(QString expression)
{
    calculator->SetFunction(expression.toLatin1().data());
    double answer = calculator->proceed();
    return answer;
}

void CalcLogic::formatAndUpdateConsole(QString userinput,double calulationResult)
{
    QString consoleText;
    QString resultText = QString().setNum(calulationResult); // see argument functions in qstring help
    if(ProgramMode == mode())
        consoleText = resultText; // only result is required in prgmode.
    else if(StatisticsMode == mode())
    {
        consoleText = "\n"+resultText;
    }
    else
        consoleText = userinput + "\n" + resultText;
    emit resultAvailable(consoleText);
    consoleText.clear();
}

void CalcLogic::formatAndUpdateByteConsole(double input, WordType conversionTo)
{
    // QString consoleText;
    //emit byteResultAvailable("Qword");
    QString resultText = QString().setNum(conversionTo);
    QString strr=convertDecToBin(mDecimalValue);

    switch(conversionTo){
    case QWord:
        emit byteResultAvailable(strr);
        break;
    case DWord:
        emit byteResultAvailable(strr.right(32));
        break;
    case Word:
        emit byteResultAvailable(strr.right(16));
        break;
    case Byte:
        emit byteResultAvailable(strr.right(8));
        break;
    }
}

void CalcLogic::clearEverything()
{
    mvalueinMemory=0;
    mUserInput.clear();
    mBraceCounter=0;
    mUserInputOperand.clear();
    formatAndUpdateConsole("",0);
    emit updateBraceCounter("");
    emit byteResultAvailable("0");
}
// This function returns the function name as a qstring depending on the
// arguments passed.
QString CalcLogic::functionNameForOperator(OperatorType functionType,UnitsType type)
{
    QString functionName;
    switch(functionType) {
    case sinvalue :
        functionName = "sin"; // make sure that this text matches with text used in algorithm.
        break;
    case cosvalue :
        functionName = "cos";
        break;
    case tanvalue :
        functionName = "tan";
        break;
    case sinhvalue :
        functionName = "sinh";
        return functionName; // sinh is not concerned about units type.
        break;
    case coshvalue :
        functionName = "cosh";
        return functionName;
        break;
    case tanhvalue :
        functionName = "tanh";
        return functionName;
        break;
    case asinvalue :
        functionName = "asin";
        break;
    case acosvalue :
        functionName = "acos";
        break;
    case atanvalue :
        functionName = "atan";
        break;
    case asinhvalue :
        functionName = "asinh";
        return functionName;
        break;
    case acoshvalue :
        functionName = "acosh";
        return functionName;
        break;
    case atanhvalue :
        functionName = "atanh";
        return functionName;
        break;
    case Sqroot :
        functionName = "sqrt";
        return functionName;
        break;
    case naturalLog:
        functionName = "ln";
        return functionName;
        break;
    case logvalue:
        functionName = "log";
        return functionName;
        break;
    case cuberoot:
        functionName = "cuberoot";
        return functionName;
        break;
    case Reciprocal:
        functionName = "reciproc";
        return functionName;
        break;
    case square:
        functionName = "sqr";
        return functionName;
        break;
    case cube:
        functionName = "cube";
        return functionName;
        break;
    case factorial:
        functionName = "fact";
        return functionName;
        break;
    case Tenpowerx:
        functionName = "powten";
        return functionName;
        break;
    case epowerx:
        functionName = "powe";
        return functionName;
        break;
    case dmsvalue:
        functionName = "dms";
        return functionName;
        break;
    case todegress:
        functionName = "degress";
        return functionName;
        break;
    case Intvalue:
        functionName = "int";
        return functionName;
        break;
    case Fracvalue:
        functionName = "frac";
        return functionName;
        break;
    };

    switch(type) {
    case Radians :
        functionName += "r";
        break;
    case Degrees :
        functionName += "d";
        break;
    case Grads :
        functionName += "g";
        break;
    };
    return functionName;
}

